package cn.tworice.common.utils;

import cn.tworice.common.vo.CodeVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.*;

/**
 * 代码生成
 * @author 二饭[tworice@sina.cn][2022/1/14 21:52]
 */
@Component
@Slf4j
public class CodeUtil {

    /**
     * 模板页面路径
     * @author 二饭[tworice@sina.cn][2022/1/11 13:06]
     */
    private String templatePath = "";

    @Value("${admin.vue-project}")
    private String vueProjectName;

    public CodeUtil(){
        templatePath=System.getProperty("user.dir")+"\\src\\main\\resources\\static\\template\\";
    }

    /**
     * 通过模板名称读取该模板内容
     * @return 返回模板内容
     * @author 二饭[tworice@sina.cn][2022/1/11 13:08]
     */
    public String readByName(String templateName) {
        File file = new File(templatePath+templateName);
        BufferedReader reader = null;
        StringBuilder sbf = new StringBuilder();
        try {
            reader = new BufferedReader(new FileReader(file));
            String tempStr;
            while ((tempStr = reader.readLine()) != null) {
                sbf.append(tempStr);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                reader.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
        return sbf.toString();
    }

    /**
     * 读取指定文件内容并返回
     * @author 二饭[tworice@sina.cn][2022/1/12 0:20]
     */
    public String readByPath(String filePath){
        File file = new File(filePath);
        BufferedReader reader = null;
        StringBuilder sbf = new StringBuilder();
        try {
            reader = new BufferedReader(new FileReader(file));
            String tempStr;
            while ((tempStr = reader.readLine()) != null) {
                sbf.append(tempStr);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                reader.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }

        }
        return sbf.toString();
    }

    /**
     * 构建Vue页面的内容
     * @author 二饭[tworice@sina.cn][2022/1/12 0:19]
     */
    public boolean buildCodeVue(CodeVO codeVO) {
        String content=readByName(codeVO.getTemplateName());
        content=content.replace("-tworice_table_item-", codeVO.getTableItem());
        content=content.replace("-tworice_form_item-", codeVO.getFormItem());
        content=content.replace("-tworice_form-", codeVO.getForm());
        content=content.replace("-tworice_url-", codeVO.getUrl());
        content=content.replace("-tworice_rules-", codeVO.getRules());
        content=content.replace("-tworice_search_item-", codeVO.getSearchItem());
        content=content.replace("-tworice_search-", codeVO.getSearch());
        content=content.replace("-tworice_dist-", codeVO.getDist());
        content=content.replace("-tworice_init_dist-", codeVO.getInitDist());
        content=content.replace("-tworice_init_dists-", codeVO.getInitDists());

        String fileName = System.getProperty("user.dir").substring(0, System.getProperty("user.dir").lastIndexOf("\\")) + "\\" + vueProjectName + "\\src\\components\\code\\" + codeVO.getPageName()+".vue";
        return createFile(fileName, content);
    }

    /**
     * @param fileName 路径+文件名称
     * @param content 要写入文件的内容
     * 创新新的文件，并写入内容
     * 如果该文件存在则删除重新创建
     * @author 二饭[tworice@sina.cn][2022/1/12 0:18]
     */
    public boolean createFile(String fileName, String content) {
        File file = new File(fileName);
        try {
            if(!file.exists()) {
                file.createNewFile();
            } else {
                file.delete();
                file.createNewFile();
            }
            FileWriter fw = new FileWriter(file);
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(content);
            bw.flush();
            bw.close();
            fw.close();
        } catch (Exception e) {
            log.error("生成文件失败"+e.getClass().toString());
            return false;
        }
        log.info("生成文件成功");
        return true;
    }

    /**
     * 获取路由信息,返回路由数组
     * @author 二饭[tworice@sina.cn][2022/1/11 21:03]
     */
    public String getRouter() {
        String file=System.getProperty("user.dir").substring(0, System.getProperty("user.dir").lastIndexOf("\\"))+ "\\" + vueProjectName + "\\src\\core\\router.js";
        String content=readByPath(file);
        content=content.substring(content.indexOf("//$start")+8, content.lastIndexOf("//$end")).trim();
        return content;
    }

    /**
     * 添加路由信息
     * @author 二饭[tworice@sina.cn][2022/1/12 0:15]
     */
    public boolean addRouter(int type, String path, String name) {
        log.info("添加路由信息");
        String router = null;

        if(type==1){
            // 添加模块路由
            router=addModule(path, name);
        }else if(type==2){
            // 添加页面路由
            router=addPage(path, name);
        }else{
            return false;
        }
        return refreshRouter(router);
    }



    /**
     * 将路由器内容写入路由表中
     * @param router 路由数组
     * @author 二饭[tworice@sina.cn][2022/1/11 23:47]
     */
    public boolean refreshRouter(String router) {
        log.info("将路由器内容写入路由表中");
        try {
            if (router != null) {
                // 路由文件位置
                String file = System.getProperty("user.dir").substring(0, System.getProperty("user.dir").lastIndexOf("\\")) + "\\" + vueProjectName + "\\src\\core\\router.js";
                // 获取路由数组信息
                String routerContent=getRouter();
                // 获取路由文件内容
                String fileContent = readByPath(file);
                String content=fileContent.substring(0,fileContent.indexOf("//$start"))+"\r\n//$start\r\n"+router+"\r\n//$end\r\n";
                content+=fileContent.substring(fileContent.indexOf("//$end")+6);
                createFile(file, content);
            }
        }catch (Exception exception){
            return false;
        }
        return true;
    }

    /**
     * 添加模块
     * @param name 路由名称
     * @param path 路由跳转路径
     * @return 返回构建好的路由数组
     * @author 二饭[tworice@sina.cn][2022/1/11 23:25]
     */
    public String addModule(String path,String name){
        log.info("添加模块路由");
        String router = getRouter();
        String content=router.substring(0,router.lastIndexOf("]"));
        StringBuilder buffer = new StringBuilder();
        // 构建添加到路由的内容
        buffer.append("{path:'");
        buffer.append(path);
        buffer.append("',");
        buffer.append("name:'");
        buffer.append(name);
        buffer.append("',");
        buffer.append("component: ()=>import('@/components/index'),");
        buffer.append("children:[]},");
        content = content + buffer.toString() + "]";

        return content;
    }

    /**
     * 添加页面路由
     * @author 二饭[tworice@sina.cn][2022/1/12 17:53]
     */
    public String addPage(String path,String name){
        log.info("添加页面路由");
        String router = getRouter(); // 路由文件内容
        StringBuilder buffer = new StringBuilder();
        // 从新增路由路径中获取模块路由的名称
        String module = path.substring(0, path.lastIndexOf("/"));
        int moduleIndex = router.indexOf(module); // 模块名称所在文件内容索引
        buffer.append(router.substring(0, moduleIndex));

        // 获取从模块开始的内容
        String moduleContent=router.substring(moduleIndex);
        int childrenIndex=moduleContent.indexOf("children");
        buffer.append(moduleContent.substring(0, childrenIndex));
        buffer.append("children:");
        String childrenContent = moduleContent.substring(childrenIndex);
        String[] children=getBracketIndex('[', ']', childrenContent);
        if(children[0].length()==2){
            buffer.append(children[0].substring(0,children[0].length() - 1));
        }else {
            String substring = children[0].substring(0, children[0].length() - 2).trim();
            buffer.append(substring);
            /*如果该路由数组最后一个]前面的符号不是逗号或中括号 则在其后加一个逗号*/
            if(!substring.substring(substring.length()-1).equals(",")&&!substring.substring(substring.length()-1).equals("[")){
                buffer.append(",");
            }
        }
        // 截取路由path
        buffer.append("{path:'");
        buffer.append(path.substring(path.lastIndexOf("/") + 1));
        buffer.append("',");
        buffer.append("name:'");
        buffer.append(name);
        buffer.append("',");
        buffer.append("component: (resolve) =>require(['@/components/code/");
        buffer.append(path.substring(path.lastIndexOf("/") + 1));
        buffer.append(".vue',], resolve),},");
        buffer.append("]");
        buffer.append(children[1]);
        return buffer.toString();
    }

    /**
     * 传入开始和结束的括号，返回括号包含的内容
     * @param beginBracket 开始的括号
     * @param endBracket 结束的括号
     * @param content 要查询的原始内容
     * @return 返回括号包含的内容，包括两个括号
     * @author 二饭[tworice@sina.cn][2022/1/12 16:45]
     */
    public String[] getBracketIndex(char beginBracket, char endBracket, String content) {
        int number=1;
        int beginIndex=content.indexOf(beginBracket);// 开始索引
        int endIndex = -1;// 结束索引

        for(int i=beginIndex+1;i<content.length();i++){
            if(content.charAt(i)==beginBracket){
                number++;
            }else if(content.charAt(i)==endBracket){
                if(number-1==0){
                    endIndex=i;
                    break;
                }else {
                    number--;
                }
            }
        }

        String[] arr = new String[2];
        arr[0]=content.substring(beginIndex, endIndex + 1).trim(); // 路由数组内容[]包括的内容
        arr[1]=content.substring(endIndex + 1).trim();// []后面的内容
        return arr;
    }
}
